interface RangeWithContainerIdType extends MyPartial<Range> {
  startOffset: number;
  endOffset: number;
  startContainerId: string;
  endContainerId: string;
  commonAncestorContainerId: string;
}

interface Position {
  index: number;
  tagName: string;
  parentTagName: string | undefined;
  isTextNode: boolean;
}

class RangeHandler {
  private position: Position[] = [];
  private anchorOffset: number = 0;

  // Set the range to a specific element
  // setRangeToElement(element: HTMLElement, start: number, end: number) {
  //   const range = document.createRange();
  //   range.setStart(element.firstChild || element, start);
  //   range.setEnd(element.firstChild || element, end);

  //   const selection = window.getSelection();
  //   if (selection) {
  //     selection.removeAllRanges();
  //     selection.addRange(range);
  //   }
  // }

  createAndInsertRange(insertNode: Node, offset: number) {
    const selection = getSelection()!;
    const range = document.createRange();

    // 清除当前的选择
    selection.removeAllRanges();
    // 添加新的range到selection中
    range.setStart(insertNode, offset);
    range.setEnd(insertNode, offset);

    selection.addRange(range);
  }

  // 获取Position，默认获取缓存的，如果想获取当前光标的Position，则会先计算并保存当前Position
  async saveCursorPosition(node?: HTMLElement) {
    this.clearPosition();
    const section = getSelection()!;
    let currentNode = node || section.anchorNode!;
    const EDITOR_ID = "edit_container";
    while (
      currentNode?.parentNode &&
      (currentNode as HTMLElement)?.id !== EDITOR_ID
    ) {
      const index = Array.from(currentNode.parentNode?.childNodes).findIndex(
        (node) => node === currentNode
      );
      const tagName =
        (currentNode as HTMLElement).tagName || currentNode.nodeName;
      const isTextNode = currentNode.nodeType === Node.TEXT_NODE;
      this.position.unshift({
        index,
        tagName: tagName,
        parentTagName: currentNode.parentElement?.tagName,
        isTextNode: isTextNode,
      });
      currentNode = currentNode.parentNode;
    }
    localStorage.setItem("position", JSON.stringify(this.position));
  }

  //保存光标偏移量
  async saveAnchorOffset(): Promise<number> {
    const section = getSelection()!;
    return new Promise((res) => {
      setTimeout(() => {
        this.anchorOffset = section.anchorOffset;
        localStorage.setItem("anchorOffset", JSON.stringify(this.anchorOffset));
        res(this.anchorOffset);
      });
    });
  }

  private getAnchorOffset() {
    if (!this.anchorOffset) {
      const anchorOffset = localStorage.getItem("anchorOffset");
      if (anchorOffset) {
        this.anchorOffset = JSON.parse(anchorOffset);
      }
    }
    return this.anchorOffset;
  }

  // 获取Position，默认获取缓存的，如果想获取当前光标的Position，则会先计算并保存当前Position
  getCursorPosition(current?: boolean) {
    if (current) this.saveCursorPosition();
    if (this.position.length <= 0) {
      const pos = localStorage.getItem("position");
      if (pos) {
        this.position = JSON.parse(pos);
      }
    }
    return this.position;
  }

  // 获取光标相对于整个editor的偏移量，因为range对象的anchorOffset是相对于当前节点的
  getCursorOffset() {
    const position = this.getCursorPosition();
    let current: ChildNode | HTMLElement = getEditorDom()!;
    let totalTextLength = 0;
    for (let item of position) {
      totalTextLength += Array.from(current?.childNodes ?? [])
        .filter((_, i) => i < item.index)
        .reduce((pre, cur) => {
          const isTextNode = cur.nodeType === Node.TEXT_NODE;
          const textContent = cur.textContent?.length || 0;
          if (isTextNode) return pre + textContent;

          const innerText = (cur as HTMLElement).innerText;
          const innerTextLength = innerText.replaceAll("\n", "").length;
          return pre + innerTextLength;
        }, 0);

      current = current?.childNodes?.[item.index];
    }
    console.log({
      totalTextLength,
      "this.anchorOffset": this.anchorOffset,
    });

    return totalTextLength + this.getAnchorOffset();
  }

  // 通过Position，找到并返回节点，用来插入光标
  findNodeByPosition(position: Position[]) {
    const ROOT_ID = "edit_container";
    let current: ChildNode | HTMLElement = document.getElementById(ROOT_ID)!;
    for (let item of position) {
      current = current.childNodes[item.index];
    }
    return current;
  }

  private clearPosition() {
    if (this.position.length > 0) {
      this.position = [];
    }
  }
}
export const rangeHandler = new RangeHandler();
